import tornado.ioloop
import tornado.netutil
import tornado.iostream
import socket

class TCPServer(object):
    def __init__(self, port):
        self._sockets = []
        self._server = None
        self._ioloop = tornado.ioloop.IOLoop.current()
        self._connections = {}

    def handle_stream(self, stream, address):
        self._connections[stream] = stream
        stream.set_close_callback(lambda: self._on_connection_close(stream))
        stream.read_until(b'\n', self._on_read)

    def _on_read(self, data, stream):
        print(f"Received: {data.decode('utf-8')}")
        stream.write(data)
        stream.read_until(b'\n', self._on_read)

    def _on_connection_close(self, stream):
        print("Connection closed")
        del self._connections[stream]

    def start(self, port):
        sockets = tornado.netutil.bind_sockets(port)
        if isinstance(sockets, list):
            sock = sockets[0]
        else:
            sock = sockets
        self._server = tornado.netutil.add_accept_handler(sock, self.handle_stream)
        self._sockets.append(sock)
        self._ioloop.start()

    def stop(self):
        self._ioloop.stop()
        for sock in self._sockets:
            sock.close()

if __name__ == "__main__":
    server = TCPServer(8888)
    server.start(8888)